﻿namespace HelperLibrary;

public class RedisStaticHelper : IDisposable
{
    //连接字符串
    public static string _connectionString;
    //实例名称
    public static string _instanceName;
    //默认数据库
    public static int _defaultDB = 0;

    public static ConcurrentDictionary<string, ConnectionMultiplexer> _connections = new ConcurrentDictionary<string, ConnectionMultiplexer>();

    /// <summary>
    /// 获取ConnectionMultiplexer
    /// </summary>
    /// <returns></returns>
    private static ConnectionMultiplexer GetConnect()
    {
        return _connections.GetOrAdd(_instanceName, p => ConnectionMultiplexer.Connect(_connectionString));
    }

    /// <summary>
    /// 获取数据库
    /// </summary>
    /// <param name="configName"></param>
    /// <param name="db">默认为0：优先代码的db配置，其次config中的配置</param>
    /// <returns></returns>
    public static IDatabase GetDatabase()
    {
        return GetConnect().GetDatabase(_defaultDB);
    }

    public static IServer GetServer(int endPointsIndex = 0)
    {
        var confOption = ConfigurationOptions.Parse(_connectionString);
        return GetConnect().GetServer(confOption.EndPoints[endPointsIndex]);
    }

    public static ISubscriber GetSubscriber()
    {
        return GetConnect().GetSubscriber();
    }
    public void Dispose()
    {
        if (_connections != null && _connections.Count > 0)
        {
            foreach (var item in _connections.Values)
            {
                item.Close();
            }
        }
    }
    public static bool SetString<T>(string key, string value, TimeSpan? expiryTime = null)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        if (value == null)
            throw new ArgumentNullException(nameof(value));

        // 使用连接的IDatabase接口来存储键值对并设置过期时间
        var db = GetDatabase();
        db.StringSet(key, value, expiryTime);
        return Exists(key);
    }
    public static async Task<bool> SetStringAsync<T>(string key, string value, TimeSpan? expiryTime = null)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        if (value == null)
            throw new ArgumentNullException(nameof(value));

        // 使用连接的IDatabase接口来存储键值对并设置过期时间
        var db = GetDatabase();
        await db.StringSetAsync(key, value, expiryTime);
        return await ExistsAsync(key);
    }
    public static bool Set<T>(string key, T value, TimeSpan? expiryTime = null)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        if (value == null)
            throw new ArgumentNullException(nameof(value));
        // 将对象序列化为字符串，然后存储到Redis中
        var serializedValue = JsonConvert.SerializeObject(value);

        // 使用连接的IDatabase接口来存储键值对并设置过期时间
        var db = GetDatabase();
        db.StringSet(key, serializedValue, expiryTime);
        return Exists(key);
    }
    public static async Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiryTime = null)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        if (value == null)
            throw new ArgumentNullException(nameof(value));
        // 将对象序列化为字符串，然后存储到Redis中
        var serializedValue = JsonConvert.SerializeObject(value);

        // 使用连接的IDatabase接口来存储键值对并设置过期时间
        var db = GetDatabase();
        await db.StringSetAsync(key, serializedValue, expiryTime);
        return await ExistsAsync(key);
    }

    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static string? GetString(string key)
    {
        if (key == null)
            return "";
        if (!Exists(key))
        {
            return "";
        }
        var db = GetDatabase();
        if (db == null)
        {
            return "";
        }
        var value = db.StringGet(key);
        if (value.IsNullOrEmpty)
        {
            return "";
        }
        return value;
    }
    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static async Task<string?> GetStringAsync(string key)
    {
        if (key == null)
            return default;
        if (!await ExistsAsync(key))
        {
            return default;
        }
        var db = GetDatabase();
        return await db.StringGetAsync(key);
    }

    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static T? Get<T>(string key)
    {
        if (key == null)
            return default;
        if (!Exists(key))
        {
            return default;
        }
        var db = GetDatabase();
        if (db == null)
        {
            return default;
        }
        var value = db.StringGet(key);
        if (value.IsNullOrEmpty)
        {
            return default;
        }
        return JsonConvert.DeserializeObject<T>(value);
    }
    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static async Task<T?> GetAsync<T>(string key)
    {
        if (key == null)
            return default;
        if (!await ExistsAsync(key))
        {
            return default;
        }
        var db = GetDatabase();
        return JsonConvert.DeserializeObject<T>(await db.StringGetAsync(key));
    }

    /// <summary>
    /// 获取缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static async Task<object?> GetAsync(string key)
    {
        if (key == null)
            return null;
        if (!await ExistsAsync(key))
        {
            return null;
        }
        var db = GetDatabase();
        return JsonConvert.DeserializeObject<object>(db.StringGetAsync(key).ToString());
    }

    /// <summary>
    /// 验证缓存项是否存在
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static async Task<bool> ExistsAsync(string key)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        var db = GetDatabase();
        return await db.KeyExistsAsync(key);
    }

    /// <summary>
    /// 验证缓存项是否存在
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static bool Exists(string key)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        var db = GetDatabase();
        return db.KeyExists(key);
    }
    /// <summary>
    /// 移除某个缓存项
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static bool Remove(string key)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        var db = GetDatabase();
        return db.KeyDelete(key);
    }
    /// <summary>
    /// 移除某个缓存项
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static async Task<bool> RemoveAsync(string key)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        var db = GetDatabase();
        return await db.KeyDeleteAsync(key);
    }

    /// <summary>
    /// 压缩为字节缓存
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <param name="expiryTime"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static async Task<bool> SetCompressedValueAsync<T>(string key, string value, TimeSpan? expiryTime = null)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        if (value == null)
            throw new ArgumentNullException(nameof(value));

        // 压缩字符串
        byte[] compressedBytes;
        using (var memoryStream = new MemoryStream())
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress))
            {
                byte[] bytesToCompress = Encoding.UTF8.GetBytes(value);
                gzipStream.Write(bytesToCompress, 0, bytesToCompress.Length);
                gzipStream.Flush();
                compressedBytes = memoryStream.ToArray();
            }
        }
        // 使用连接的IDatabase接口来存储键值对并设置过期时间
        var db = GetDatabase();
        await db.StringSetAsync(key, compressedBytes, expiryTime);
        return await ExistsAsync(key);
    }
    /// <summary>
    /// 压缩为字节缓存
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <param name="expiryTime"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static async Task<bool> SetCompressedValueAsync<T>(string key, T value, TimeSpan? expiryTime = null)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        if (value == null)
            throw new ArgumentNullException(nameof(value));
        // 将对象序列化为字符串，然后存储到Redis中
        var serializedValue = JsonConvert.SerializeObject(value);

        // 压缩字符串
        byte[] compressedBytes;
        using (var memoryStream = new MemoryStream())
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress))
            {
                byte[] bytesToCompress = Encoding.UTF8.GetBytes(serializedValue);
                gzipStream.Write(bytesToCompress, 0, bytesToCompress.Length);
                gzipStream.Flush();
                compressedBytes = memoryStream.ToArray();
            }
        }
        // 使用连接的IDatabase接口来存储键值对并设置过期时间
        var db = GetDatabase();
        await db.StringSetAsync(key, compressedBytes, expiryTime);
        return await ExistsAsync(key);
    }

    /// <summary>
    /// 压缩为字节缓存
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="key"></param>
    /// <param name="value"></param>
    /// <param name="expiryTime"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static bool SetCompressedValue<T>(string key, T value, TimeSpan? expiryTime = null)
    {
        if (key == null)
            throw new ArgumentNullException(nameof(key));
        if (value == null)
            throw new ArgumentNullException(nameof(value));
        // 将对象序列化为字符串，然后存储到Redis中
        var serializedValue = JsonConvert.SerializeObject(value);

        // 压缩字符串
        byte[] compressedBytes;
        using (var memoryStream = new MemoryStream())
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Compress))
            {
                byte[] bytesToCompress = Encoding.UTF8.GetBytes(serializedValue);
                gzipStream.Write(bytesToCompress, 0, bytesToCompress.Length);
                gzipStream.Flush();
                compressedBytes = memoryStream.ToArray();
            }
        }
        // 使用连接的IDatabase接口来存储键值对并设置过期时间
        var db = GetDatabase();
        db.StringSet(key, compressedBytes, expiryTime);
        return Exists(key);
    }
    /// <summary>
    /// 获取压缩字节缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static async Task<T> GetDecompressedValueAsync<T>(string key)
    {
        if (key == null)
            return default;
        if (!await ExistsAsync(key))
        {
            return default;
        }
        var db = GetDatabase();
        var compressedBytes = await db.StringGetAsync(key);
        if (compressedBytes.IsNull)
        {
            return default;
        }
        // 解压缩
        byte[] bytes;
        using (var memoryStream = new MemoryStream(compressedBytes))
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
            {
                byte[] buffer = new byte[4096];
                using (var memoryStreamOutput = new MemoryStream())
                {
                    int count = gzipStream.Read(buffer, 0, buffer.Length);
                    while (count > 0)
                    {
                        memoryStreamOutput.Write(buffer, 0, count);
                        count = gzipStream.Read(buffer, 0, buffer.Length);
                    }
                    bytes = memoryStreamOutput.ToArray();
                }
            }
        }
        var str = Encoding.UTF8.GetString(bytes);
        return JsonConvert.DeserializeObject<T>(str);
    }

    /// <summary>
    /// 获取压缩字节缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static T GetDecompressedValue<T>(string key)
    {
        if (key == null)
            return default;
        if (!Exists(key))
        {
            return default;
        }
        var db = GetDatabase();
        var compressedBytes = db.StringGet(key);
        if (compressedBytes.IsNull)
        {
            return default;
        }
        // 解压缩
        byte[] bytes;
        using (var memoryStream = new MemoryStream(compressedBytes))
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
            {
                byte[] buffer = new byte[4096];
                using (var memoryStreamOutput = new MemoryStream())
                {
                    int count = gzipStream.Read(buffer, 0, buffer.Length);
                    while (count > 0)
                    {
                        memoryStreamOutput.Write(buffer, 0, count);
                        count = gzipStream.Read(buffer, 0, buffer.Length);
                    }
                    bytes = memoryStreamOutput.ToArray();
                }
            }
        }
        var str = Encoding.UTF8.GetString(bytes);
        return JsonConvert.DeserializeObject<T>(str);
    }
    /// <summary>
    /// 获取压缩为字节缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static async Task<object> GetDecompressedValueAsync(string key)
    {
        if (key == null)
            return null;
        if (!await ExistsAsync(key))
        {
            return null;
        }
        var db = GetDatabase();
        var compressedBytes = await db.StringGetAsync(key);
        if (compressedBytes.IsNull)
        {
            return default;
        }
        // 解压缩
        byte[] bytes;
        using (var memoryStream = new MemoryStream(compressedBytes))
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
            {
                byte[] buffer = new byte[4096];
                using (var memoryStreamOutput = new MemoryStream())
                {
                    int count = gzipStream.Read(buffer, 0, buffer.Length);
                    while (count > 0)
                    {
                        memoryStreamOutput.Write(buffer, 0, count);
                        count = gzipStream.Read(buffer, 0, buffer.Length);
                    }
                    bytes = memoryStreamOutput.ToArray();
                }
            }
        }
        var str = Encoding.UTF8.GetString(bytes);
        return JsonConvert.DeserializeObject<object>(str);
    }

    /// <summary>
    /// 获取压缩为字节缓存
    /// </summary>
    /// <param name="key">缓存Key</param>
    /// <returns></returns>
    public static object GetDecompressedValue(string key)
    {
        if (key == null)
            return null;
        if (!Exists(key))
        {
            return null;
        }
        var db = GetDatabase();
        var compressedBytes = db.StringGet(key);
        if (compressedBytes.IsNull)
        {
            return default;
        }
        // 解压缩
        byte[] bytes;
        using (var memoryStream = new MemoryStream(compressedBytes))
        {
            using (var gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
            {
                byte[] buffer = new byte[4096];
                using (var memoryStreamOutput = new MemoryStream())
                {
                    int count = gzipStream.Read(buffer, 0, buffer.Length);
                    while (count > 0)
                    {
                        memoryStreamOutput.Write(buffer, 0, count);
                        count = gzipStream.Read(buffer, 0, buffer.Length);
                    }
                    bytes = memoryStreamOutput.ToArray();
                }
            }
        }
        var str = Encoding.UTF8.GetString(bytes);
        return JsonConvert.DeserializeObject<object>(str);
    }
}